package network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;


import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import data.CompanyInfo;
import data.DepartmentData;
import data.DepartmentList;
import data.GetOrderListResponse;
import data.LoginResponse;
import data.Order;
import data.OrderDepartment;
import data.OrderElement;
import data.OrderResponse;
import data.ProductInfo;
import data.ProductList;
import data.SaveResponse;
import data.Order.OrderState;

public class NetworkManager {

	public static final String BASE_URI = "https://karlkar.nazwa.pl/AdmelWebService/";

	private static Gson gson = null;
	private static HttpClient httpClient = HttpClientBuilder.create().build();

	public static NetworkManager instance = null;

	private NetworkManager() {
		GsonBuilder builder = new GsonBuilder();
		builder.enableComplexMapKeySerialization();

		builder.registerTypeAdapter(DepartmentData.class, DepartmentData.serializer);
		builder.registerTypeAdapter(Order.class, Order.serializer);
		builder.registerTypeAdapter(OrderDepartment.class, OrderDepartment.serializer);
		builder.registerTypeAdapter(OrderElement.class, OrderElement.serializer);

		builder.registerTypeAdapter(OrderResponse.class, OrderResponse.deserializer);
		builder.registerTypeAdapter(GetOrderListResponse.class, GetOrderListResponse.deserializer);
		builder.registerTypeAdapter(LoginResponse.class, LoginResponse.deserializer);
		builder.registerTypeAdapter(SaveResponse.class, SaveResponse.deserializer);
		
		builder.registerTypeAdapter(OrderState.class, OrderState.deserializer);
		builder.registerTypeAdapter(Order.class, Order.deserializer);
		builder.registerTypeAdapter(OrderDepartment.class, OrderDepartment.deserializer);
		builder.registerTypeAdapter(OrderElement.class, OrderElement.deserializer);
		builder.registerTypeAdapter(ProductList.class, ProductList.deserializer);
		builder.registerTypeAdapter(ProductInfo.class, ProductInfo.deserializer);
		builder.registerTypeAdapter(CompanyInfo.class, CompanyInfo.deserializer);
		builder.registerTypeAdapter(DepartmentData.class, DepartmentData.deserializer);
		builder.registerTypeAdapter(DepartmentList.class, DepartmentList.deserializer);
		gson = builder.create();
	}

	public static NetworkManager getInstance() {
		if (instance == null)
			instance = new NetworkManager();
		return instance;
	}
	
	public LoginResponse login(String username, String password) {
		LoginResponse loginStatus = new LoginResponse();
		BufferedReader rd = null;
		HttpPost req = new HttpPost(BASE_URI + "login");

		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("username", username));
			nameValuePairs.add(new BasicNameValuePair("password", password));
			req.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			StringBuilder respBuilder = new StringBuilder();
			String line = "";
			while ((line = rd.readLine()) != null)
				respBuilder.append(line);
			System.out.println("LoginResponse = " + respBuilder.toString());
			loginStatus = gson.fromJson(respBuilder.toString(), LoginResponse.class);
			return loginStatus;
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return loginStatus;
	}

	public ProductList getProductsData() {
		ProductList products = null;
		BufferedReader rd = null;
		HttpGet req = new HttpGet(BASE_URI + "getProductData");
		HttpResponse resp;
		try {
			resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			String inputLine;
			StringBuilder response = new StringBuilder();
			while ((inputLine = rd.readLine()) != null)
				response.append(inputLine);

			System.out.println("ProductList = " + response.toString());
			products = gson.fromJson(response.toString(), ProductList.class);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return products;
	}
	
	public DepartmentList getDepartments() {
		DepartmentList departments = null;
		BufferedReader rd = null;
		HttpGet req = new HttpGet(BASE_URI + "getDepartments");
		HttpResponse resp;
		try {
			resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			String inputLine;
			StringBuilder response = new StringBuilder();
			while ((inputLine = rd.readLine()) != null)
				response.append(inputLine);

			System.out.println("DepartmentList = " + response.toString());
			departments = gson.fromJson(response.toString(), DepartmentList.class);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return departments;
	}

	public GetOrderListResponse getSubmittedOrders() {
		GetOrderListResponse orders = null;
		BufferedReader rd = null;
		HttpGet req = new HttpGet(BASE_URI + "getSubmittedOrders");
		HttpResponse resp;
		try {
			resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			String inputLine;
			StringBuilder response = new StringBuilder();
			while ((inputLine = rd.readLine()) != null)
				response.append(inputLine);

			System.out.println("OrderList = " + response.toString());
			orders = gson.fromJson(response.toString(), GetOrderListResponse.class);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return orders;
	}

	public SaveResponse saveOrder(Order order) {
		SaveResponse status = new SaveResponse();
		BufferedReader rd = null;
		HttpPost req = new HttpPost(BASE_URI + "saveOrder");

		try {
			String str = gson.toJson(order);
			req.setEntity(new StringEntity(str));
			HttpResponse resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			StringBuilder respBuilder = new StringBuilder();
			String line = "";
			while ((line = rd.readLine()) != null)
				respBuilder.append(line);
			System.out.println("SaveResonse = " + respBuilder.toString());
			status = gson.fromJson(respBuilder.toString(), SaveResponse.class);
			return status;
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return status;
	}
	
	public GetOrderListResponse getOrderList() {
		GetOrderListResponse orderList = null;
		BufferedReader rd = null;
		HttpGet req = new HttpGet(BASE_URI + "getOrderList");
		HttpResponse resp;
		try {
			resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			String inputLine;
			StringBuilder response = new StringBuilder();
			while ((inputLine = rd.readLine()) != null)
				response.append(inputLine);

			System.out.println("GetOrderListResponse = " + response.toString());
			orderList = gson.fromJson(response.toString(), GetOrderListResponse.class);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return orderList;
	}

	public OrderResponse getOrder(int mDbId) {
		OrderResponse orderResponse = null;
		BufferedReader rd = null;
		HttpPost req = new HttpPost(BASE_URI + "getOrder");
		
		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
			nameValuePairs.add(new BasicNameValuePair("orderId", String.valueOf(mDbId)));
			req.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse resp = httpClient.execute(req);
			rd = new BufferedReader(new InputStreamReader(resp.getEntity().getContent()));

			StringBuilder respBuilder = new StringBuilder();
			String line = "";
			while ((line = rd.readLine()) != null)
				respBuilder.append(line);
			System.out.println("OrderResponse = " + respBuilder.toString());
			orderResponse = gson.fromJson(respBuilder.toString(), OrderResponse.class);
		} catch (ClientProtocolException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (rd != null) {
				try {
					rd.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return orderResponse;
	}
}
